﻿using JetBrains.Annotations;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;

namespace System.ComponentModel.DataAnnotations;

/// <summary>
/// Specifies an index to be generated in the database.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class IndexAttribute : Attribute
{
    private bool? _isUnique;

    private string _name;

    /// <summary>
    /// The properties which constitute the index, in order.
    /// </summary>
    public IReadOnlyList<string> PropertyNames
    {
        get;
    }

    /// <summary>
    /// The name of the index.
    /// </summary>
    public string Name
    {
        get
        {
            return _name;
        }
        [param: NotNull]
        set
        {
            _name = Check.NotNull(value, "value");
        }
    }

    /// <summary>
    /// Whether the index is unique.
    /// </summary>
    public bool IsUnique
    {
        get
        {
            return _isUnique.GetValueOrDefault();
        }
        set
        {
            _isUnique = value;
        }
    }

    /// <summary>
    /// Checks whether Microsoft.EntityFrameworkCore.IndexAttribute.IsUnique has been explicitly set to a value.
    /// </summary>
    public bool IsUniqueHasValue => _isUnique.HasValue;

    /// <summary>
    /// Initializes a new instance of the Microsoft.EntityFrameworkCore.IndexAttribute class.
    /// </summary>
    /// <param name="propertyNames">The properties which constitute the index, in order (there must be at least one).</param>
    public IndexAttribute([CanBeNull] params string[] propertyNames)
    {
        Check.NotNullOrEmpty(propertyNames, "propertyNames");
        if (propertyNames.Any(r => r.IsNullOrEmpty()))
        {
            throw new ArgumentException(nameof(propertyNames) + " all can not be null or empty!", nameof(propertyNames));
        }
        PropertyNames = propertyNames.ToList();
    }
}
